package CORE;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import CONEXAO.Conexao;

public class GenericDAO<T> {

	protected final String BANCO = "livros"; 
	protected String tabela;	
	private Class<T> typeClass;
	
	public GenericDAO(String tabela, Class<T> classe) {
		this.tabela = tabela;
		typeClass = classe;
	}
		
	public boolean incluir(T instance) {
		try {
			Connection conn = Conexao.conectar(BANCO);						
			PreparedStatement ps = conn.prepareStatement(gerarSQLIncluir());						
			setarPSIncluir(ps, instance);						
			ps.execute();
			ps.close();
			conn.close();
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}
	
	public String gerarSQLIncluir(){		
		StringBuilder sql = new StringBuilder();                        
        sql.append("INSERT INTO ");
        sql.append(tabela);
        sql.append(" ( ");
        
        StringBuilder sql2 = new StringBuilder();
                        
        boolean descricao = typeClass.getSuperclass().toString().equalsIgnoreCase("class CORE.GenericDTODescricao");
        if(descricao){
        	sql.append(typeClass.getSuperclass().getDeclaredFields()[0].getName());
        	sql2.append("?");
        }
        
        for(int i = 0; i < typeClass.getDeclaredFields().length; i++){
        	if(i == 0 && descricao){        		
        		sql.append(" , ");        		
        		sql.append(typeClass.getDeclaredFields()[i].getName());        		
        		sql2.append(",?");
        	} else if(i == 0 && !descricao){
        		sql.append(typeClass.getDeclaredFields()[i].getName());
        		sql2.append("?");
        	} else {
        		sql2.append(",?");
        		sql.append(" , ");
        		sql.append(typeClass.getDeclaredFields()[i].getName());
        	}
        }
        
        sql.append(") VALUES ( ");
        sql.append(sql2);
        sql.append(");");        
        return sql.toString();
	}
	
	public boolean alterar(T instance) {
		try {
			Connection conn = Conexao.conectar(BANCO);			
			PreparedStatement ps = conn.prepareStatement(gerarSQLAlterar());
			setarPSAlterar(ps, instance);
			ps.execute();
			ps.close();
			conn.close();
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}
	
	public String gerarSQLAlterar(){		
		StringBuilder sql = new StringBuilder();                        
        sql.append("UPDATE ");
        sql.append(tabela);        
        sql.append(" SET ");              
        
        boolean descricao = typeClass.getSuperclass().toString().equalsIgnoreCase("class CORE.GenericDTODescricao");
        if(descricao){        	
        	sql.append(typeClass.getSuperclass().getDeclaredFields()[0].getName());
        	sql.append(" = (?) ");
        }
        
        for(int i = 0; i < typeClass.getDeclaredFields().length; i++){
        	if(i == 0 && descricao){        		
        		sql.append(" , ");        		
        		sql.append(typeClass.getDeclaredFields()[i].getName());        		
        		sql.append(" = (?) ");
        	} else if(i == 0 && !descricao){        		
        		sql.append(typeClass.getDeclaredFields()[i].getName());
        		sql.append(" = (?) ");
        	} else {
        		sql.append(", ");        		
        		sql.append(typeClass.getDeclaredFields()[i].getName());
        		sql.append(" = (?) ");
        	}
        }
        sql.append("WHERE codigo = (?);");                      
        return sql.toString();
	}
	
	public boolean remover(T instance) {
		try {
			Connection conn = Conexao.conectar(BANCO);
			PreparedStatement ps = conn.prepareStatement(gerarSQLRemover());
			setarPSExcluir(ps, instance);

			ps.execute();
			ps.close();

			conn.close();

			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}
	
	public String gerarSQLRemover(){
		StringBuilder sql = new StringBuilder();                        
        sql.append("DELETE FROM ");
        sql.append(tabela);
        sql.append(" WHERE codigo = (?);");
        return sql.toString();
	}
			
	public T pesquisarPorCodigo(long id){
		try{            
            T instace = null;
            Connection conn = Conexao.conectar(BANCO);
            StringBuilder sql = new StringBuilder();                        
            sql.append("SELECT * FROM ");
            sql.append(tabela);
            sql.append(" WHERE codigo = (?);");
            
            PreparedStatement ps = conn.prepareStatement(sql.toString());
            ps.setLong(1, id);
            
            ResultSet rs = ps.executeQuery();
            if(rs.next()){
            	instace = criarObjeto(rs);
            }
                        
            rs.close();
            ps.close();
            
            conn.close();
            
            return instace;
        } catch (Exception e) {
            e.printStackTrace();   
            return null;
        }        		
	}
	
	public List<T> pesquisarTodos(){
		try{            
            List<T> Ts = new ArrayList<T>();
            Connection conn = Conexao.conectar(BANCO);
            StringBuilder sql = new StringBuilder();                        
            sql.append("SELECT * FROM ");
            sql.append(tabela);                        
                        
            ResultSet rs = conn.prepareStatement(sql.toString()).executeQuery();
            while(rs.next()){
                Ts.add(criarObjeto(rs));
            }
                        
            rs.close();                        
            conn.close();
            
            return Ts;
        } catch (Exception e) {            
            e.printStackTrace();   
            return null;
        }        
	}		
	
	public T criarObjeto(ResultSet rs) throws SQLException { return null; }	
	
	public void setarPSExcluir(PreparedStatement ps, T instance) throws SQLException{ }
	
	public void setarPSAlterar(PreparedStatement ps, T instance) throws SQLException{ }
	
	public void setarPSIncluir(PreparedStatement ps, T instance) throws SQLException{	}
}